package Day_0223.Spring;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * @author zxc
 * @date 2023/02/23 14:49
 **/
public class Interfaces_Affect_MultipleBeans {
    public static void main(String[] args) throws Exception {
        /**
         * 第一大类：影响多个Bean的接口
         * ===》
         * 1.实现了这些接口的Bean，会切入到多个Bean的生命周期中。
         * 正因为如此，这些接口的功能非常强大，Spring内部扩展也经常使用这些接口，例如自动注入以及AOP的实现都和他们有关。
         * （1）InstantiationAwareBeanPostProcessor
         *  ===》作用于 Bean的实例化前后;
         * （2）BeanPostProcessor
         *  ===》作用于 Bean的初始化前后;
         *
         * 2.Spring扩展中最重要的两个接口！
         * （1）InstantiationAwareBeanPostProcessor作用于实例化阶段的前后，
         * （2）BeanPostProcessor作用于初始化阶段的前后。
         *  ==》正好和第一、第三个生命周期阶段对应。
         *
         * 3.InstantiationAwareBeanPostProcessor接口
         * 1）InstantiationAwareBeanPostProcessor实际上继承了BeanPostProcessor接口。
         * 从生命周期角度，重点关注其特有的对实例化阶段的影响
         * InstantiationAwareBeanPostProcessor extends BeanPostProcessor
         *
         * 2）InstantiationAwareBeanPostProcessor接口源码分析：
         * ===》
         * （1）PostProcessBeforeInstantiation方法 ：
         *  ===》
         *  可以看到，postProcessBeforeInstantiation方法是会 在doCreateBean方法之前被调用，也就是在bean实例化之前调用的，
         *  英文源码注释解释道，该方法的返回值会替换原本的Bean作为代理，这也是Aop等功能实现的关键点。
         *
         * （2）PostProcessAfterInstantiation方法 ：
         *  ===》
         *  可以看到该方法在属性赋值方法PopulateBean内，但是在真正执行赋值操作之前。
         *  其返回值为boolean，返回false时可以阻断属性赋值阶段
         *  注意 ：continueWithPropertyPopulation属性的值，默认位true。
         *
         * 3）BeanPostProcessor接口：
         * ===》
         * （1）PostProcessBeforeInitialization方法 ：即，在Bean进行初始化之前调用该方法;
         * （2）PostProcessAfterInitialization方法 ：即，在Bean进行初始化之后调用该方法;
         * （3）BeanPostProcessor接口源码 ：
         *
         * public interface BeanPostProcessor {
         * //bean初始化之前调用
         * @Nullable
         * default Object postProcessBeforeInitialization(Object bean, String beanName)
         * throws BeansException {return bean;}
         *
         * //bean初始化之后调用
         * @Nullable
         * default Object postProcessAfterInitialization(Object bean, String beanName)
         * throws BeansException {return bean;}
         * }
         *
         *
         */
        Student student = new Student();
        student.init();
        student.init2();
        student.afterPropertiesSet();
    }
    @Component("student")
    public static class Student implements InitializingBean {
        private String name;
        private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        //1.使用postconstrtct注解
        @PostConstruct
        public void init(){
            System.out.println("执行 init方法");
        }
        //2.在xml配置文件中配置init-method方法
        public void init2(){
            System.out.println("执行init2方法 ");
        }
        //3.实现InitializingBean接口
        public void afterPropertiesSet() throws Exception {
            System.out.println("执行init3方法");
        }
    }
}

